﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Threading;
namespace AndroidEditor.Compiler
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks></remarks>
    class CompilerEr
    {
        /// <summary>
        /// 
        /// </summary>
        private System.Diagnostics.Process process = new System.Diagnostics.Process();
        /// <summary>
        /// 
        /// </summary>
        private string compiler = "";
        /// <summary>
        /// 
        /// </summary>
        private string sysrootStr = "";
        /// <summary>
        /// 
        /// </summary>
        private string File = "";
        /// <summary>
        /// 
        /// </summary>
        private int Error = 0;
        /// <summary>
        /// 
        /// </summary>
        private string ErrorMessage = "";
        /// <summary>
        /// 
        /// </summary>
        private string CompilerLineString = "";
        /// <summary>
        /// 
        /// </summary>
        private List<string> DepLibs = new List<string>();
        /// <summary>
        /// 
        /// </summary>
        private List<string> DepHead = new List<string>();
        /// <summary>
        /// 
        /// </summary>
        private ProjectSetting settingItem = new ProjectSetting("NONE");
        /// <summary>
        /// 
        /// </summary>
        private System.Timers.Timer timer = new System.Timers.Timer(1000);
        /// <summary>
        /// 
        /// </summary>
        private DateTime EndTime = DateTime.Now;
        /// <summary>
        /// 
        /// </summary>
        private string PlatFormFlag = "";
        /// <summary>
        /// Initializes a new instance of the <see cref="CompilerEr"/> class.
        /// </summary>
        /// <remarks></remarks>
        public CompilerEr()
        {
            timer.Interval = 500;

            timer.Enabled = true;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

        }

        /// <summary>
        /// Handles the Elapsed event of the timer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Timers.ElapsedEventArgs"/> instance containing the event data.</param>
        /// <remarks></remarks>
        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            DateTime time = DateTime.Now;

            if (EndTime.Hour == time.Hour && EndTime.Minute == time.Minute && EndTime.Second == time.Second)
            {
                timer.Stop();
                if (!process.HasExited)
                {

                    process.Kill();
                    Error = 1;
                    ErrorMessage = "操作超时！";
                }

            }
            else
            {
                Application.DoEvents();
            }

        }




        /// <summary>
        /// Gets the error code.
        /// </summary>
        /// <remarks></remarks>
        public int ErrorCode
        {
            get
            {
                return Error;
            }

        }
        /// <summary>
        /// Gets the error mes.
        /// </summary>
        /// <remarks></remarks>
        public string ErrorMes
        {
            get
            {
                return ErrorMessage;
            }

        }

        /// <summary>
        /// Gets the compiler line.
        /// </summary>
        /// <remarks></remarks>
        public string CompilerLine
        {
            get
            {
                return CompilerLineString;
            }

        }

        /// <summary>
        /// Sets the compier.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <remarks></remarks>
        public void SetCompier(string compiler)
        {
            this.compiler = compiler;
        }

        /// <summary>
        /// Sets the root sys.
        /// </summary>
        /// <param name="sysrootStr">The sysroot STR.</param>
        /// <remarks></remarks>
        public void SetRootSys(string sysrootStr)
        {
            this.sysrootStr = sysrootStr;
        }

        /// <summary>
        /// Starts this instance.
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public string Start()
        {
            string outfile = Path.GetFileNameWithoutExtension(this.File);
            if (outfile.Trim() == "")
            {
                return "";
            }
            List<string> cstr = new List<string>();

            cstr.Add("-c");
            cstr.Add(File);

            cstr.Add(PlatFormFlag);
            foreach (string Item in DepLibs)
            {
                cstr.Add("-L" + Item);
            }
            foreach (string Item in DepHead)
            {
                cstr.Add("-I" + Item);
            }
            foreach (FileSetting Item in settingItem.GetHeadSetting().GetItem())
            {
                cstr.Add(Item.GetFile());
            }
            foreach (string  KeyItem  in  settingItem.GetLibs())
            {
                cstr.Add(settingItem.GetLibs()[KeyItem].ToString());
            }
            foreach (string KeyItem in settingItem.GetFlags())
            {
                cstr.Add(settingItem.GetFlags()[KeyItem].ToString());
            }
            cstr.Add("-o");
            outfile = outfile + ".o";
            cstr.Add(settingItem.GetOutDir() + outfile);
            cstr.Add(sysrootStr);

            process.StartInfo.FileName = compiler;
            process.StartInfo.Arguments = string.Join(" ", cstr.ToArray());
            Console.WriteLine(string.Join(" ", cstr.ToArray()));
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow = true;

            Error = 2;
            ErrorMessage = "编译未完成!";
            try
            {
                EndTime = DateTime.Now.AddMinutes(10);

                timer.Start();
                process.Start();

                process.WaitForExit();
                if (Error != 1)
                {
                    timer.Stop();
                    Error = process.ExitCode;

                    ErrorMessage = process.StandardError.ReadToEnd();
                }

            }
            catch (Exception ex)
            {

            }
            cstr.Insert(0, compiler);

            CompilerLineString = string.Join(" ", cstr.ToArray());
            process.Close();
            process.Dispose();

            return outfile;
        }

        /// <summary>
        /// Sets the file.
        /// </summary>
        /// <param name="fileitem">The fileitem.</param>
        /// <remarks></remarks>
        public void SetFile(string fileitem)
        {
            this.File = fileitem.Replace(@"\", "/");

        }

        /// <summary>
        /// Sets the depend libs.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <remarks></remarks>
        public void SetDependLibs(List<string> list)
        {
            this.DepLibs = list;
        }

        /// <summary>
        /// Sets the depend head.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <remarks></remarks>
        public void SetDependHead(List<string> list)
        {
            this.DepHead = list;
        }

        /// <summary>
        /// Sets the project.
        /// </summary>
        /// <param name="settingItem">The setting item.</param>
        /// <remarks></remarks>
        public void SetProject(ProjectSetting settingItem)
        {
            this.settingItem = settingItem;
        }

        /// <summary>
        /// Sets the plat form flag.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <remarks></remarks>
        public void SetPlatFormFlag(string value)
        {
            this.PlatFormFlag = value;
        }
    }
}
